04. The Module Pattern
Private Properties: Literal
By default, most things things are publicly accessible in JavaScript. We can use closure to make certain parts of an app private, but what if we want to prevent access to a property directly? That is, how would we make a property or method private so it's inaccessible from the outside world? To lend a bit more context, check out a plain object literal handles privacy:
let developer = {
name: 'Veronika',
getName: function () {
return this.name;
}
};
We can access the string value 'Veronika' with the getName method, as well as directly by accessing the developer object's name property:
developer.getName();
// 'Veronika'
developer.name;
// 'Veronika'
However, what happens when we reassign the object's name property?
developer.name = 'Not Veronika';
developer.getName();
// 'Not Veronika'
developer.name;
// 'Not Veronika'
This sort of open access makes developers uncomfortable. Since we can directly access and mutate an object's properties, we would like a way to implement private properties.
💡Privacy with Underscores? 💡
You may have seen object properties and method names prefixed with an underscore (
_), especially in library code. While an underscore is added by the code's author to distinguish privacy, it is privacy by convention only. JavaScript does not give special functionality or meaning to properties prefixed with an underscore!
Private Properties: Function
Let's look into another option: using a function. What if we create a basic function that just returns an object? Does this give the object an adequate level of protection?
Let's look a bit more closely. Check out the following instantiateDeveloper() function:
function instantiateDeveloper() {
return {
name: 'Veronika',
getName: function () {
return this.name;
}
};
}
Nothing too surprising -- just a basic function that returns an object with two properties: name and getName. Let's go ahead and invoke the function and get the returned object. We'll assign the returned object to a variable, developer:
let developer = instantiateDeveloper();
As it turns out, the string 'Veronika' is still accessible, because the two aforementioned properties still exist in the object being returned from instantiateDeveloper():
developer.getName;
// 'Veronika'
developer.name;
// 'Veronika'
Along with direct access, we can mutate and reassign the value of the name property as well:
developer.name = 'Not Veronika';
developer.name;
// 'Not Veronika'
Wrapping an object within a function doesn't seem too effective either. So, how can we go about making an object's properties private?
No Private Properties
Since JavaScript has no concept of private properties out-of-the-box, there is no special syntax or keyword we can use to protect certain properties from being accessed.
However, there is hope! Recall from earlier lessons that we can use scope and closures to create a private state. Let's look at a quick refresher:
function myCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
let counter = myCounter();
Note that the myCounter() function closes over the count variable. The value of count increments as the function is called:
counter();
// 1
counter();
// 2
However, there is no way that any method outside the closure itself can access count:
counter.count;
// undefined
count;
// undefined
So, closure provides a way to create private data. How can we leverage these same techniques -- with scope and closures -- to create private properties and methods in an object?
L4 35 Intro Modules
Quiz: Scope (review)
SOLUTION:
- `myName`
- `you`
- `message`
Quiz: IIFE (review)
SOLUTION:
Two strings: `'Formula: NaCl'` and `'Molar Mass: 58.44 g/mol'`💡Need Review? 💡
The Module Pattern leverages many of the powerful features of JavaScript, such as scope, closures, and immediately-invoked function expressions (IIFE). If any of this material feels largely unfamiliar, or if you simply want a review to freshen things up, check out Lesson 2: Functions at Runtime.
40 - SC - Module Pattern Demo
The Module Pattern: Recap
Before moving on to the next section, let's make sure we're on the same page regarding the Module Pattern. We'll be improving upon it in the very next section! Consider the following:
let diana = (function () {
let secretIdentity = 'Diana Prince';
return {
introduce: function () {
console.log(`Hi! I am ${secretIdentity}`);
}
};
})();
Recall that one of the key ingredients here is the IIFE! Not only does it prevent pollution of the global scope (which hinders the chance of variable name collisions) -- the IIFE helps prevent access to the secretIdentity variable.
console.log(diana.secretIdentity);
// undefined
And because the returned object's introduce() method retains access to its parent function's scope, we are given a public interface to interact with secretIdentity:
diana.introduce();
// 'Hi! I am Diana Prince'
Other Benefits of the Module Pattern
The Module Pattern is commonly used to create private properties in JavaScript, but there are quite a few other benefits of incorporating the Module Pattern in code that you write as well. For one: organization. Modules are a larger unit of organization than, say, functions or objects. This helps partition code and provide structure as an application scales.
Keep in mind, however, that you generally use the Module Pattern when you just want one "version" of an object. If you're looking to instantiate unique objects that follow a certain blueprint, you can always still write and invoke a constructor function!
Module Pattern Facts
SOLUTION:
- The Module Pattern uses closures to create private properties
- The Module Pattern requires the use of IIFE's
- Unlike calling a constructor function, implementing the Module Pattern returns just one version of an object
Summary
Since JavaScript doesn't have private variables, properties, or methods built-in, we can leverage the Module Pattern to enforce such privacy. At its core, the Module Pattern leverages scope, closures, and (commonly) IIFE's to not only hide data from external access, but to also provide a public interface for such data.
In the next section, we'll check out another variation: the Revealing Module Pattern.
Further Research
- Addy Osmani's The Module Pattern (JavaScript Design Patterns)
- Todd Motto's Mastering the Module Pattern